package info.wangyuan.agent.utils;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import info.wangyuan.agent.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 微信应用开发工具类
 *
 * @author PNut
 * @version 20240520
 */
@Slf4j
public class WechatUtils {
    private static final String API_URL_ROOT = "https://***.***.***/"; // 微信 API 根目录
    private static final String API_URL_GET_ACCESS_TOKEN = "/api/xxx"; // 获取 AccessToken
    private static final String API_URL_GET_OAUTH_REDIRECT = "/api/xxx"; // 获取授权跳转地址
    private static final String API_URL_GET_OAUTH_INFO = "/api/xxx"; // 通过 Code 换取授权信息
    private static final String API_URL_CHECK_SUBSCRIBED = "/api/xxx"; // 判断是否关注
    private static final String API_URL_GET_ACCESS_INFO = "/api/xxx"; // 获取 AccessToken
    private static final String API_URL_SEND_TEMPLATE_MESSAGE = "/api/xxx"; // 推送模板消息
    private static final String API_URL_SEND_TAG_TEMPLATE_MESSAGE = "/api/xxx"; // 对标签用户推送模板消息
    private static final String API_URL_OAUTH_CALLBACK = "/api/xxx"; // 微信网页授权回调

    private static final Set<String> OAUTH_APP = new HashSet<>();
    private static final Map<String, String> TEMPLATE = new HashMap<>();

    static {
        OAUTH_APP.add("xxx");
    }

    static {
        TEMPLATE.put("xxx", "xxx");
    }

    private WechatUtils() {
    }

    public static String getTemplate(String key) {
        return TEMPLATE.get(key);
    }

    /**
     * 判断是否关注公众号
     */
    public static boolean checkSubscribed(String openId) {
        String result = sendHttpGetRequest(API_URL_ROOT + API_URL_CHECK_SUBSCRIBED + "/" + openId);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        return jsonObject.getStr("data").equals("1");
    }

    /**
     * 获取授权跳转地址
     *
     * @param state 应用标识
     */
    public static String getOAuthRedirectUrl(String state) {
        try {
            String result = sendHttpGetRequest(API_URL_ROOT + API_URL_GET_OAUTH_REDIRECT + "/" + state);
            JSONObject jsonObject = JSONUtil.parseObj(result);
            return jsonObject.getStr("data");
        } catch (Exception e) {
            log.error("获取授权跳转地址失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 获取授权跳转地址
     *
     * @param state 应用标识
     * @param scope 授权方式（snsapi_base/snsapi_userinfo）
     */
    public static String getOAuthRedirectUrl(String state, String scope) {
        try {
            String result = sendHttpGetRequest(API_URL_ROOT + API_URL_GET_OAUTH_REDIRECT + "/" + state + "/" + scope);
            JSONObject jsonObject = JSONUtil.parseObj(result);
            return jsonObject.getStr("data");
        } catch (Exception e) {
            log.error("获取授权跳转地址失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 通过code获取授权信息
     */
    public static String getOAuthInfo(String code) {
        try {
            return sendHttpGetRequest(API_URL_ROOT + API_URL_GET_OAUTH_INFO + "/" + code);
        } catch (Exception e) {
            log.error("通过code获取授权信息失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 通过code获取openId
     */
    public static String getOpenIdByCode(String code) {
        try {
            JSONObject jsonObject = JSONUtil.parseObj(getOAuthInfo(code));
            return jsonObject.getJSONObject("data").getStr("id");
        } catch (Exception e) {
            log.error("通过code获取openId失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 通过code获取用户信息
     */
    public static Map<String, Object> getUserinfoByCode(String code) {
        try {
            JSONObject jsonObject = JSONUtil.parseObj(getOAuthInfo(code));
            return jsonObject.getJSONObject("data");
        } catch (Exception e) {
            log.error("通过code获取用户信息失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 推送模板消息
     *
     * @param data 格式需为 <h3>{"keyword1"="value","keyword2"="值","keyword3"=...}</h3>
     */
    public static String sendTplMessage(String openid, String jumpUrl, String tplId, Map<String, String> data) {
        Map<String, Object> dataMap = generateTemplateData(data);
        Map<String, Object> json = new HashMap<>();
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            json.put("url", jumpUrl);
            json.put("data", objectMapper.writeValueAsString(dataMap));
            objectMapper = new ObjectMapper();
            String jsonString = objectMapper.writeValueAsString(json);
            String url = API_URL_ROOT + API_URL_SEND_TEMPLATE_MESSAGE + "/" + openid + "/" + tplId;
            return sendHttpPostRequest(url, jsonString);
        } catch (JsonProcessingException ex) {
            log.error("推送模板消息时出错: {}", ex.getMessage());
            return null;
        }
    }

    /**
     * 生成模板data
     *
     * @param map < keyword, value>
     * @return 格式需为 {"keyword1" = "value1","keyword2" = "value2"...}
     */
    public static Map<String, Object> generateTemplateData(Map<String, String> map) {
        Map<String, Object> data = new HashMap<>();
        String color = "#173177"; // 微信已弃用自定义颜色功能
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            Map<String, String> keywordMap = new HashMap<>();
            keywordMap.put("value", value);
            keywordMap.put("color", color);
            data.put(key, keywordMap);
        }
        return data;
    }

    /**
     * 发送 get 请求
     */
    private static String sendHttpGetRequest(String url) {
        try {
            RestTemplate restTemplate = new RestTemplate();
            return restTemplate.getForObject(url, String.class);
        } catch (Exception e) {
            throw new BusinessException("发送 get 请求失败", e);
        }
    }

    /**
     * 发送 post 请求
     */
    private static String sendHttpPostRequest(String url, String body) {
        HttpResponse response = HttpUtil.createPost(url)
                .body(body)
                .timeout(3 * 60 * 1000)
                .execute();
        if (response.isOk()) {
            return response.body();
        } else {
            log.error("发送post请求失败: status: {}", response.getStatus());
            log.error("body: {}", response.body());
            return null;
        }
    }
}
